// 类型判断
function type(target) {
  let template = {
    "[object Null]": "null",
    "[object String]": "string - object",
    "[object Number]": "number - object",
    "[object Boolean]": "boolean - object",
    "[object Object]": "object",
    "[object Array]": "array",
    "[object Date]": "date",
    "[object RegExp]": "regExp",
  };
  let tos = Object.prototype.toString.call(target);
  let ret = typeof target;
  if (ret !== "object") {
    return ret;
  } else if (template[tos] !== undefined) {
    return template[tos];
  } else {
    return "other";
  }
}

// 数组去重
// 返回去重后数组，数组项可以有引用类型
if (!Array.prototype.unique) {
  Array.prototype.unique = function () {
    let arr = [],
      len = this.length;
    if (len) {
      for (let i = 0; i < len; i++) {
        let arrLen = arr.length,
          count = 0;
        for (let j = 0; j < arrLen; j++) {
          arr[j] == this[i] && count++;
        }
        !count && arr.push(this[i]);
      }
    }
    return arr;
  };
}
//在数组自己身上去重(数组项不能有引用数据类型)
if (!Array.prototype.unique) {
  Array.prototype.unique = function () {
    let temp = {},
      len = this.length;
    if (len) {
      for (let i = 0; i < len; i++) {
        if (temp[this[i]]) {
          continue;
        } else {
          temp[this[i]] = 1;
        }
      }
      this.length = 0;
      for (let prop in temp) {
        this.push(prop);
      }
    }
  };
}
//返回去重后的数组(数组项不能有引用数据类型)
if (!Array.prototype.unique) {
  Array.prototype.unique = function () {
    let temp = {},
      arr = [],
      len = this.length;
    if (len) {
      for (let i = 0; i < len; i++) {
        if (!temp[this[i]]) {
          temp[this[i]] = 1;
          arr.push(this[i]);
        }
      }
      return arr;
    }
  };
}

// 拷贝
// 浅拷贝
function clone(Origin, Target) {
  var Target =
    Target ||
    (Object.prototype.toString.call(Origin) === "[object Array]" ? [] : {});
  for (var prop in Origin) {
    if (Origin.hasOwnProperty(prop)) {
      Target[prop] = Origin[prop];
    }
  }
  return Target;
}
// 深拷贝
function deepClone(Origin, Target) {
  var Target =
    Target ||
    (Object.prototype.toString.call(Origin) === "[object Array]" ? [] : {});
  for (var prop in Origin) {
    if (Origin.hasOwnProperty(prop)) {
      if (Origin[prop] !== null && typeof Origin[prop] === "object") {
        Target[prop] = deepClone(Origin[prop]);
      } else {
        Target[prop] = Origin[prop];
      }
    }
  }
  return Target;
}

// 封装原生ajax
//var option = { //实参option对象
//   url: "", //url
//   type: "", //get/post
//   data: {}, //需要把data中的属性遍历拼接好
//   beforeSend: function () {},
//   success: function (res) {},
//   error: function (err) {},
// };
function ajax(option) {
  var url = option.url;
  var type = option.type.toUpperCase() || "get";
  var data = option.data;
  var dataStr = "";

  if (typeof data == "object") {
    for (var key in data) {
      if (data.hasOwnProperty(key)) {
        dataStr += key + "=" + data[key] + "&";
      }
    }
    if (dataStr.length != 0) {
      dataStr = dataStr.slice(0, -1);
    }
  }

  var xhr = null;
  //兼容写法
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
  } else {
    xhr = new ActiveXObject("Microsoft.XMLHTTP"); //ie5 6
  }

  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
      if (xhr.status == 200) {
        // 获取响应头部
        var contentType = xhr.getResponseHeader("Content-Type");
        // console.log("contentType:", contentType);
        var res;
        //判断响应的数据格式 json xml str
        if (contentType.indexOf("json") > -1) {
          var jsonStr = xhr.responseText;
          res = JSON.parse(jsonStr);
        } else if (contentType.indexOf("xml") > -1) {
          res = xhr.responseXML;
        } else {
          res = xhr.responseText;
        }

        if (option.success) {
          option.success(res);
        }
      } else {
        if (option.error) {
          option.error("请求响应失败");
        }
      }
    } else {
      if (option.beforeSend) {
        option.beforeSend();
      }
    }
  };

  if (type == "GET") {
    url = url + "?" + dataStr;
  }
  xhr.open(type, url, true);
  if (type == "POST") {
    //如果是post，设置请求头信息
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send(dataStr);
  } else {
    xhr.send(null);
  }
}

// 封装loadScript函数，动态加载（异步加载）js脚本 全都兼容非常好用
function loadScript(url, callback) {
  var script = document.createElement("script");
  script.type = "text/javascript";
  if (script.readyState) {
    //判断是否为ie
    script.onreadystatechange = function () {
      if (script.readyState == "complete" || script.readyState == "loaded") {
        callback();
      }
    };
  } else {
    //不是ie就执行这个
    script.onload = function () {
      callback();
    };
  }
  script.src = url;
  document.body.appendChild(script);
}

// 封装鼠标拖拽元素drag方法，依赖getStyle方法
function drag(el) {
  var disX, disY;
  function move(e) {
    el.style.left = e.pageX - disX + "px";
    el.style.top = e.pageY - disY + "px";
  }
  el.addEventListener(
    "mousedown",
    function (e) {
      disX = e.pageX - parseInt(getStyle(el, "left"));
      disY = e.pageY - parseInt(getStyle(el, "top"));
      document.addEventListener("mousemove", move, false);
      document.addEventListener(
        "mouseup",
        function (e) {
          document.removeEventListener("mousemove", move, false);
        },
        false
      );
    },
    false
  );
}

// 封装cancelHandler方法阻止默认事件
function cancelHandler(e) {
  if (e.preventDefault) {
    e.preventDefault();
  } else {
    e.returnValue = false;
  }
}

// 取消事件冒泡 都兼容
function stopBubble(event) {
  if (event.stopPropagation) {
    event.stopPropagation();
  } else {
    event.cancelBubble = true;
  }
}

// 封装addEvent兼容性方法，添加事件处理器 都兼容
function addEvent(el, type, handle) {
  if (el.addEventListener) {
    el.addEventListener(type, handle, false);
  } else if (el.attachEvent) {
    el.attachEvent("on" + type, function () {
      handle.call(elem);
    });
  } else {
    elem["on" + type] = handle;
  }
}

// 封装getStyle获取元素计算样式 都兼容 常用
function getStyle(el, prop) {
  if (window.getComputedStyle) {
    return window.getComputedStyle(el, null)[prop];
  } else {
    return el.currentStyle[prop];
  }
}

// 封装getScrollOffset获取滚动条滚动距离 都兼容
function getScrollOffset() {
  if (window.pageXOffset) {
    return {
      x: window.pageXOffset,
      y: window.pageYOffset,
    };
  } else {
    return {
      x: document.body.scrollLeft + document.documentElement.scrollLeft,
      y: document.body.scrollTop + document.documentElement.scrollTop,
    };
  }
}

// 封装一个getViewportOffset兼容方法，获取视口尺寸
// 都兼容，混杂模式标准模式都好使
function getViewportOffset() {
  if (window.innerWidth) {
    return {
      w: window.innerWidth,
      h: window.innerHeight,
    };
  } else {
    if (document.compatMode === "BackCompat") {
      return {
        w: document.body.clientWidth,
        h: document.body.clientHeight,
      };
    } else {
      return {
        w: document.documentElement.clientWidth,
        h: document.documentElement.clientHeight,
      };
    }
  }
}

// 封装myChildren获取元素的子元素集合数组 都兼容
if (!Element.prototype.myChildren) {
  Element.prototype.myChildren = function () {
    let children = this.childNodes,
      len = children.length,
      arr = [];

    for (let i = 0; i < len; i++) {
      children[i].nodeType == 1 && arr.push(children[i]);
    }
    return arr;
  };
}

//获取元素的第n层父元素 ie9及以下不兼容
function retParent(el, n) {
  while (el && n) {
    el = el.parentElement;
    n--;
  }
  return el;
}

// 封装hasChildren判断元素是否有子元素节点 都兼容
if (!Element.prototype.hasChildren) {
  Element.prototype.hasChildren = function () {
    let children = this.childNodes,
      len = children.length;

    for (let i = 0; i < len; i++) {
      if (children[i].nodeType == 1) {
        return true;
      }
    }
    return false;
  };
}

// 封装getSibling，获取元素后面的（n>0）第n个兄弟元素,
// 或前面的（n<0）第n个兄弟元素，n==0,返回自身 ie9及以下不兼容
if (!Element.prototype.getSibling) {
  Element.prototype.getSibling = function (n) {
    let el = this;
    while (n && el) {
      if (n > 0) {
        if (el.nextElementSibling) {
          el = el.nextElementSibling;
        } else {
          for (
            el = el.nextSibling;
            el && el.nodeType != 1;
            el = el.nextSibling
          );
        }
        n--;
      } else if (n < 0) {
        if (el.previousElementSibling) {
          el = el.previousElementSibling;
        } else {
          for (
            el = el.previousSibling;
            el && el.nodeType != 1;
            el = el.previousSibling
          );
        }
        n++;
      }
    }
    return el;
  };
}

// 对应Element上的insertBefore
// 封装insertAfter方法，在元素节点前面添加元素节点，感觉没啥用 ie9及以下不兼容
if (!Element.prototype.insertAfter) {
  Element.prototype.insertAfter = function (a, b) {
    if (this.lastElementChild == b) {
      this.appendChild(a);
    } else {
      let next = b.nextElementSibling;
      this.insertBefore(a, next);
    }
  };
}

// 封装reverseChildren将标签内部元素节点逆序 感觉没啥用 ie4、ie5不兼容
if (!Element.prototype.reverseChildren) {
  Element.prototype.reverseChildren = function () {
    let children = this.children;
    let len = children.length;
    let removed = [];

    for (let i = 0; i < len; i++) {
      removed.push(this.removeChild(children[0]));
    }
    removed.reverse();
    for (let j = 0; j < len; j++) {
      this.appendChild(removed[j]);
    }
  };
}

//封装方法设置、获取、或者删除cookie
//setCookie参数：obj（Object）里是要存储的键值对；time（Number）为有效期天数
// getCookie参数：传入一个你想要获取的cookie名即可
// removeCookie参数；传入你想要删除的cookie名，支持一次性传入多个cookie名
function setCookie(obj, time) {
  const date = new Date().getTime();
  const dateStr = new Date(date + time * 24 * 60 * 60 * 1000).toUTCString();
  for (var key in obj) {
    document.cookie = key + "=" + obj[key] + ";expires=" + dateStr;
  }
}
function getCookie(attr) {
  var reg = new RegExp("(^|\\s)" + attr + "=([^;]+)(;|$)");
  var value = document.cookie.match(reg)[2];
  return value;
}
function removeCookie() {
  var obj = {};
  for (var i = 0; i < arguments.length; i++) {
    obj[arguments[i]] = "";
  }

  setCookie(obj, -1);
}
